﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Diagnostics;

namespace SimpleIR
{
	/// <summary>
	/// Represents simple variable expressions.
	/// </summary>
	public sealed class IRVarExp
	{
		public readonly IRVarName Name;
		public readonly IRType VarType;

		public IRVarExp(IRType etype, IRVarName ln)
		{
			this.Name = ln;
			this.VarType = etype;
		}

		public override String ToString()
		{ return this.Name.ToString(); }
	}

	/// <summary>
	/// Represents simple literal expressions.
	/// </summary>
	public sealed class IRLiteralExp
	{
		//List of possible values that this literal might represent
		private readonly long m_litval = Int64.MinValue;
		private readonly double m_flit = Double.NaN;
		private readonly string m_strlit = null;
		private readonly bool m_isnull = false;

		/// <summary>
		/// The type of this literal value.
		/// </summary>
		public readonly IRType LiteralType;

		private IRLiteralExp(IRType etype, long lv, double dv, string sv, bool inull)
		{
			this.m_litval = lv;
			this.m_flit = dv;
			this.m_strlit = sv;
			this.m_isnull = inull;

			this.LiteralType = etype;
		}

		public static IRLiteralExp MakeSignedIntegralLiteral(IRType etype, long lv)
		{
			Debug.Assert(etype != null && (etype is IRSignedIntegerType));
			return new IRLiteralExp(etype, lv, Double.NaN, null, false);
		}

		public static IRLiteralExp MakeFloatLiteral(IRType etype, double fv)
		{
			Debug.Assert(etype != null && (etype is IRFloatingPointType));
			return new IRLiteralExp(etype, 0, fv, null, false);
		}

		public static IRLiteralExp MakeStringLiteralExp(IRType etype, string s)
		{
			Debug.Assert(etype != null && (etype is IRPtrType) && (((IRPtrType)etype).PtrTargetType is IRClassType));
			return new IRLiteralExp(etype, 0, Double.NaN, s, false);
		}

		public static IRLiteralExp MakeNullLiteralExp(IRPtrType etype)
		{
			Debug.Assert(etype != null);
			return new IRLiteralExp(etype, 0, Double.NaN, null, true);
		}

		public override String ToString()
		{
			if(this.m_isnull)
				return "null";
			else if(this.LiteralType is IRPrimitiveType)
			{
				IRPrimitiveType pty = (IRPrimitiveType)this.LiteralType;
				if(pty is IRSignedIntegerType)
					return this.m_litval.ToString();
				else
					return this.m_flit.ToString();
			}
			else
				return "\"" + this.m_strlit + "\"";
		}

		public long IntVal
		{
			get
			{
				Debug.Assert(this.LiteralType is IRSignedIntegerType);
				return this.m_litval;
			}
		}

		public double FloatVal
		{
			get
			{
				Debug.Assert(this.LiteralType is IRFloatingPointType);
				return this.m_flit;
			}
		}

		public String StringVal
		{
			get
			{
				Debug.Assert(this.LiteralType is IRPtrType);
				return this.m_strlit;
			}
		}
	}
}
